package com.qsw.pagenumberview.view;

import android.content.Context;
import android.graphics.Paint;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.qsw.pagenumberview.R;

import java.util.ArrayList;
import java.util.List;

/**
 * 页码控件
 */
public class PageNumberView extends LinearLayout {
    private static final int COUNT_MAX_SHOW_PAGE_BUTTON_MAX = 10;// 同时显示出来的最大页码数字按钮量的最大值
    private static final int KEY_PNV_BUTTON_TAG = ((int) System.currentTimeMillis()) | 0x40000000;

    private static final int DEFAULT_RB_PADDING = 3;// 默认值，按钮内边距，单位：dp
    private static final int DEFAULT_RB_MARGIN_LR = 5;// 默认值，按钮左右外边距，单位：dp
    private static final int DEFAULT_RB_MIN_WIDTH = 25;// 默认值，按钮最小宽度，单位：dp
    private static final int DEFAULT_TEXT_SIZE = 11;// 默认值，按钮字号，单位：sp
    private static final int DEFAULT_COUNT_MAX_SHOW_PAGE_BUTTON = 5;// 默认值，同时显示出来的最大页码数字按钮量

    private static final int TYPE_BUTTON_LASTPAGE = -1;// 下一页
    private static final int TYPE_BUTTON_NEXTPAGE = -2;// 上一页
    private static final int TYPE_BUTTON_HOMEPAGE = -3;// 首页
    private static final int TYPE_BUTTON_TAILPAGE = -4;// 尾页
    private static final int TYPE_BUTTON_JUMP = -5;// 跳转

    private RadioGroup mRgPageView;
    private Button mBtnLastPage;
    private Button mBtnNextPage;

    private LinearLayout mLlHomePage;
    private Button mBtnHomePage;
    private TextView mTvHomePagePoint;

    private LinearLayout mLlTailPage;
    private Button mBtnTailPage;
    private TextView mTvTailPagePoint;

    private LinearLayout mLlJumpView;
    private TextView mTvJump;
    private TextView mTvJumpPage;
    private EditText mEtJump;
    private Button mBtnJump;

    private final List<RadioButton> mRbNumberPageList = new ArrayList<>();

    /**
     * 按钮左右内边距，单位：dp
     */
    private int mRbLRPadding = DEFAULT_RB_PADDING;
    /**
     * 按钮上下内边距，单位：dp
     */
    private int mRbTBPadding = DEFAULT_RB_PADDING;
    /**
     * 按钮左右外边距，单位：dp
     */
    private int mRbLRMargin = DEFAULT_RB_MARGIN_LR;
    /**
     * 按钮最小宽度，单位：dp
     */
    private int mRbMinWidth = DEFAULT_RB_MIN_WIDTH;
    /**
     * 按钮字号，单位：sp
     */
    private int mTextSize = DEFAULT_TEXT_SIZE;
    /**
     * 按钮背景，应为selector，分为state_checked="true"和state_checked="false"
     */
    private int mRbBgDrawableId = R.drawable.pnv_selector_bg_rb;

    /**
     * 同时显示出来的最大页码数字按钮量
     */
    private byte mMaxShowPageBtnCount = DEFAULT_COUNT_MAX_SHOW_PAGE_BUTTON;
    /**
     * 最大页码
     */
    private int mMaxPage = 1;
    /**
     * 当前页码，从1开始
     */
    private int mCurrPage;

    /**
     * 是否显示跳转界面
     */
    private boolean mShowJumpView = true;
    /**
     * 跳转界面位置
     */
    private int mJumpViewGravity = Gravity.RIGHT;

    private String mLastPageButtonStr;
    private String mNextPageButtonStr;
    private String mHomePageButtonStr = "1";
    private String mTailPageButtonStr = String.valueOf(mMaxPage);

    private String mJumpTextStr;
    private String mJumpPageTextStr;
    private String mJumpButtonStr;

    private OnPageChangeListener mOnPageChangeListener;

    public PageNumberView(Context context) {
        super(context);
        init();
    }

    public PageNumberView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PageNumberView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        initAllView();

        disposePageChange(1);
    }

    /**
     * 根据当前配置初始化所有界面
     */
    private void initAllView() {
        removeAllViews();

        mRgPageView = new RadioGroup(getContext());
        mRgPageView.setOrientation(HORIZONTAL);

        if (mShowJumpView) {
            mLlJumpView = new LinearLayout(getContext(), null, 0);
            mLlJumpView.setOrientation(HORIZONTAL);
            mLlJumpView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
        }

        if (mShowJumpView) {
            if ((mJumpViewGravity & Gravity.TOP) == Gravity.TOP) {
                setOrientation(VERTICAL);
                setGravity(Gravity.RIGHT);
                mLlJumpView.setPadding(mLlJumpView.getPaddingLeft(),
                        mLlJumpView.getPaddingTop(),
                        mLlJumpView.getPaddingRight(),
                        mRbTBPadding);
                addView(mLlJumpView);
                addView(mRgPageView);
            } else if ((mJumpViewGravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
                setOrientation(VERTICAL);
                setGravity(Gravity.RIGHT);
                mLlJumpView.setPadding(mLlJumpView.getPaddingLeft(),
                        mRbTBPadding,
                        mLlJumpView.getPaddingRight(),
                        mLlJumpView.getPaddingBottom());
                addView(mRgPageView);
                addView(mLlJumpView);
            } else if ((mJumpViewGravity & Gravity.START) == Gravity.START | (mJumpViewGravity & Gravity.LEFT) == Gravity.LEFT) {
                setOrientation(HORIZONTAL);
                setGravity(Gravity.CENTER_VERTICAL);
                addView(mLlJumpView);
                addView(mRgPageView);
            } else if ((mJumpViewGravity & Gravity.END) == Gravity.END | (mJumpViewGravity & Gravity.RIGHT) == Gravity.RIGHT) {
                setOrientation(HORIZONTAL);
                setGravity(Gravity.CENTER_VERTICAL);
                addView(mRgPageView);
                addView(mLlJumpView);
            } else {
                setOrientation(HORIZONTAL);
                setGravity(Gravity.CENTER_VERTICAL);
                addView(mRgPageView);
                addView(mLlJumpView);
            }
        } else {
            setOrientation(HORIZONTAL);
            addView(mRgPageView);
        }

        if (getContext() != null) {
            setButtonText(getContext().getString(R.string.pnv_page_last),
                    getContext().getString(R.string.pnv_page_next));
            setJumpText(getContext().getString(R.string.pnv_page_jump_text),
                    getContext().getString(R.string.pnv_page_text),
                    getContext().getString(R.string.pnv_page_jump));
        }

        initAllChildView();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    /**
     * 设置上一页、下一页显示文字
     *
     * @param lastPageStr 上一页显示文字
     * @param nextPageStr 下一页显示文字
     */
    public void setButtonText(String lastPageStr, String nextPageStr) {
        mLastPageButtonStr = lastPageStr;
        mNextPageButtonStr = nextPageStr;

        if (mBtnLastPage != null) {
            mBtnLastPage.setText(mLastPageButtonStr);
        }
        if (mBtnNextPage != null) {
            mBtnNextPage.setText(mNextPageButtonStr);
        }
    }

    /**
     * 设置页码跳转相关文字
     *
     * @param jumpTextStr   跳转提示文字
     * @param jumpPageStr   跳转页码单位文字
     * @param jumpButtonStr 跳转按钮文字
     */
    public void setJumpText(String jumpTextStr, String jumpPageStr, String jumpButtonStr) {
        mJumpTextStr = jumpTextStr;
        mJumpPageTextStr = jumpPageStr;
        mJumpButtonStr = jumpButtonStr;

        if (mTvJump != null) {
            mTvJump.setText(mJumpTextStr);
        }
        if (mTvJumpPage != null) {
            mTvJumpPage.setText(mJumpPageTextStr);
        }
        if (mBtnJump != null) {
            mBtnJump.setText(mJumpButtonStr);
        }
    }

    /**
     * 设置尾页显示文字
     *
     * @param tailPageStr 尾页显示文字
     */
    private void setTailPageBtnText(String tailPageStr) {
        mTailPageButtonStr = tailPageStr;

        if (mBtnTailPage != null) {
            mBtnTailPage.setText(mTailPageButtonStr);
        }
    }

    /**
     * 根据当前配置重新初始化所有按钮并绘制
     */
    private void initAllChildView() {
        mRgPageView.removeAllViews();
        mRbNumberPageList.clear();

        mBtnLastPage = new Button(getContext(), null, 0);
        mBtnLastPage.setText(mLastPageButtonStr);
        mBtnLastPage.setTag(KEY_PNV_BUTTON_TAG, TYPE_BUTTON_LASTPAGE);
        initButtonStyle(mBtnLastPage);
        mRgPageView.addView(mBtnLastPage);

        mLlHomePage = new LinearLayout(getContext(), null, 0);
        mLlHomePage.setOrientation(LinearLayout.HORIZONTAL);
        mRgPageView.addView(mLlHomePage);
        mBtnHomePage = new Button(getContext(), null, 0);
        mBtnHomePage.setText(mHomePageButtonStr);
        mBtnHomePage.setTag(KEY_PNV_BUTTON_TAG, TYPE_BUTTON_HOMEPAGE);
        initButtonStyle(mBtnHomePage);
        mLlHomePage.addView(mBtnHomePage);
        mTvHomePagePoint = new TextView(getContext(), null, 0);
        mTvHomePagePoint.setText("···");
        initTextViewStyle(mTvHomePagePoint, true, false);
        mLlHomePage.addView(mTvHomePagePoint);

        mLlTailPage = new LinearLayout(getContext(), null, 0);
        mLlTailPage.setOrientation(LinearLayout.HORIZONTAL);
        mRgPageView.addView(mLlTailPage);
        mTvTailPagePoint = new TextView(getContext(), null, 0);
        mTvTailPagePoint.setText("···");
        initTextViewStyle(mTvTailPagePoint, true, false);
        mLlTailPage.addView(mTvTailPagePoint);
        mBtnTailPage = new Button(getContext(), null, 0);
        mBtnTailPage.setText(mTailPageButtonStr);
        mBtnTailPage.setTag(KEY_PNV_BUTTON_TAG, TYPE_BUTTON_TAILPAGE);
        initButtonStyle(mBtnTailPage);
        mLlTailPage.addView(mBtnTailPage);

        mBtnNextPage = new Button(getContext(), null, 0);
        mBtnNextPage.setText(mNextPageButtonStr);
        mBtnNextPage.setTag(KEY_PNV_BUTTON_TAG, TYPE_BUTTON_NEXTPAGE);
        initButtonStyle(mBtnNextPage, true);
        mRgPageView.addView(mBtnNextPage);

        initPageNumRbCount();

        mLlJumpView.removeAllViews();

        if (mShowJumpView) {
            mTvJump = new TextView(getContext(), null, 0);
            mTvJump.setText(mJumpTextStr);
            initTextViewStyle(mTvJump, false, false);
            mLlJumpView.addView(mTvJump);

            mEtJump = new EditText(getContext());
            refreshJumpEtText();
            initTextViewStyle(mEtJump, false, false);
            mEtJump.setSingleLine();
            mEtJump.setBackgroundResource(R.drawable.pnv_bg_et);
            mEtJump.setPadding(mRbLRPadding, mRbTBPadding, mRbLRPadding, mRbTBPadding);
            Paint paint = new Paint();
            paint.setTextSize(PNVUtil.sp2px(getContext(), mTextSize));
            mEtJump.setWidth((int) PNVUtil.getTextBigWidth("8888", paint));
            InputFilter[] filters = new InputFilter[1];
            filters[0] = new InputFilter.LengthFilter(String.valueOf(Integer.MAX_VALUE).length() - 1);
            mEtJump.setFilters(filters);
            mEtJump.setInputType(InputType.TYPE_CLASS_NUMBER);
            mLlJumpView.addView(mEtJump);

            mTvJumpPage = new TextView(getContext(), null, 0);
            mTvJumpPage.setText(mJumpPageTextStr);
            initTextViewStyle(mTvJumpPage, false, false);
            mLlJumpView.addView(mTvJumpPage);

            mBtnJump = new Button(getContext(), null, 0);
            mBtnJump.setText(mJumpButtonStr);
            mBtnJump.setTag(KEY_PNV_BUTTON_TAG, TYPE_BUTTON_JUMP);
            initButtonStyle(mBtnJump, true);
            mLlJumpView.addView(mBtnJump);
        }
    }

    /**
     * 初始化页码按钮个数
     */
    private void initPageNumRbCount() {
        int needAddCount = Math.max(1, Math.min(mMaxShowPageBtnCount, mMaxPage)) - mRbNumberPageList.size();
        if (needAddCount > 0) {
            for (byte i = 0; i < needAddCount; i++) {
                RadioButton radioButton = new RadioButton(getContext(), null, 0);
                initButtonStyle(radioButton);
                mRbNumberPageList.add(radioButton);
                mRgPageView.addView(radioButton, mRbNumberPageList.size() + 1);
            }
        } else if (needAddCount < 0) {
            for (int addCount = needAddCount; addCount < 0; addCount++) {
                RadioButton remove = mRbNumberPageList.remove(mRbNumberPageList.size() - 1);
                mRgPageView.removeView(remove);
            }
        }

        refreshPageNumRbText();

        refreshHomeTailViewVisibility();
    }

    /**
     * 刷新页码文字、选中、可用状态
     */
    private void refreshPageNumRbText() {
        if (mCurrPage < 1 || mCurrPage > mMaxPage) {
            return;
        }
        int leftCount = mMaxShowPageBtnCount / 2 - ((mMaxShowPageBtnCount % 2 == 0) ? 1 : 0);
        int setPageNum;
        if (mCurrPage < mMaxPage - leftCount) {
            // 从头部计算
            setPageNum = Math.max(1, mCurrPage - leftCount);
        } else {
            // 从尾部计算
            setPageNum = Math.max(1, mMaxPage - mMaxShowPageBtnCount + 1);
        }

        for (RadioButton radioButton : mRbNumberPageList) {
            radioButton.setText(String.valueOf(setPageNum));
            radioButton.setTag(KEY_PNV_BUTTON_TAG, setPageNum);
            if (mCurrPage == setPageNum) {
                mRgPageView.check(radioButton.getId());
            }

            setPageNum++;
        }

        // 前方没有页码了
        mBtnLastPage.setEnabled(mCurrPage != 1);
        // 后方没有页码了
        mBtnNextPage.setEnabled(mCurrPage != mMaxPage);
    }

    /**
     * 刷新首页、尾页界面可见状态
     */
    private void refreshHomeTailViewVisibility() {
        if (mRbNumberPageList == null || mRbNumberPageList.size() == 0) {
            return;
        }

        Object tag = mRbNumberPageList.get(0).getTag(KEY_PNV_BUTTON_TAG);
        int tagInt;
        if (tag instanceof Integer) {
            tagInt = (int) tag;
            if (tagInt > 1) {
                mLlHomePage.setVisibility(VISIBLE);
                mTvHomePagePoint.setVisibility(tagInt > 2 ? VISIBLE : GONE);
            } else {
                mLlHomePage.setVisibility(GONE);
            }
        }

        tag = mRbNumberPageList.get(mRbNumberPageList.size() - 1).getTag(KEY_PNV_BUTTON_TAG);
        if (tag instanceof Integer) {
            tagInt = (int) tag;
            if (tagInt < mMaxPage) {
                mLlTailPage.setVisibility(VISIBLE);
                mTvTailPagePoint.setVisibility((tagInt < mMaxPage - 1) ? VISIBLE : GONE);
            } else {
                mLlTailPage.setVisibility(GONE);
            }
        }
    }

    /**
     * 刷新跳转页码输入框文字
     */
    private void refreshJumpEtText() {
        if (!mShowJumpView || mEtJump == null) {
            return;
        }

        mEtJump.setText(String.valueOf(mCurrPage));
    }

    /**
     * 设置按钮样式
     *
     * @param button 要设置的按钮
     */
    private void initButtonStyle(Button button) {
        initButtonStyle(button, false);
    }

    /**
     * 设置按钮样式
     *
     * @param button         要设置的按钮
     * @param addRightMargin 是否增加右侧外边距
     */
    private void initButtonStyle(Button button, boolean addRightMargin) {
        if (button instanceof RadioButton) {
            ((RadioButton) button).setButtonDrawable(null);
        }
        button.setBackgroundResource(mRbBgDrawableId);
        button.setMinWidth(PNVUtil.dp2px(getContext(), mRbMinWidth));
        int paddingLRPx = PNVUtil.dp2px(getContext(), mRbLRPadding);
        int paddingTBPx = paddingLRPx;
        button.setPadding(paddingLRPx, paddingTBPx, paddingLRPx, paddingTBPx);

        initTextViewStyle(button, true, addRightMargin);

        button.setOnClickListener(mOnClickListener);
    }

    /**
     * 设置文字样式
     *
     * @param textView       要设置的控件
     * @param addLeftMargin  是否增加左侧外边距
     * @param addRightMargin 是否增加右侧外边距
     */
    private void initTextViewStyle(TextView textView, boolean addLeftMargin, boolean addRightMargin) {
        textView.setTextSize(mTextSize);
        textView.setGravity(Gravity.CENTER);

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
        );
        int lrMarginPx = PNVUtil.dp2px(getContext(), mRbLRMargin);
        params.setMargins(addLeftMargin ? lrMarginPx : 0, 0, addRightMargin ? lrMarginPx : 0, 0);
        textView.setLayoutParams(params);
    }

    /**
     * 获取总页码
     *
     * @return 总页码
     */
    public int getMaxPage() {
        return mMaxPage;
    }

    /**
     * 设置总页码，最小为1
     *
     * @param maxPage 总页码，最小为1
     */
    public void setMaxPage(int maxPage) {
        this.mMaxPage = Math.max(1, maxPage);

        setTailPageBtnText(String.valueOf(mMaxPage));

        if (mCurrPage > mMaxPage) {
            disposePageChange(mMaxPage);
        }

        initPageNumRbCount();
    }

    /**
     * 获取当前页码
     *
     * @return 当前页码
     */
    public int getPage() {
        return mCurrPage;
    }

    /**
     * 设置当前页码，最小为1
     *
     * @param page 当前页码，最小为1
     */
    public void setPage(int page) {
        disposePageChange(page);
    }

    /**
     * 获取显示页码按钮的最多个数
     *
     * @return 显示页码按钮的罪多个数
     */
    public byte getMaxShowPageBtnCount() {
        return mMaxShowPageBtnCount;
    }

    /**
     * 设置显示页码按钮的最多个数
     *
     * @param maxShowPageBtnCount 显示页码按钮的罪多个数
     */
    public void setMaxShowPageBtnCount(byte maxShowPageBtnCount) {
        if (maxShowPageBtnCount < 1) {
            this.mMaxShowPageBtnCount = 1;
        } else if (maxShowPageBtnCount > COUNT_MAX_SHOW_PAGE_BUTTON_MAX) {
            this.mMaxShowPageBtnCount = COUNT_MAX_SHOW_PAGE_BUTTON_MAX;
        } else {
            this.mMaxShowPageBtnCount = maxShowPageBtnCount;
        }

        initPageNumRbCount();
    }

    /**
     * 获取字号，单位：sp
     *
     * @return 字号，单位：sp
     */
    public int getTextSize() {
        return mTextSize;
    }

    /**
     * 设置字号，单位：sp
     *
     * @param textSizeSP 字号，单位：sp
     */
    public void setTextSize(int textSizeSP) {
        this.mTextSize = textSizeSP;

        initAllChildView();
    }

    /**
     * 设置按钮背景，应为selector，分为state_checked="true"和state_checked="false"
     *
     * @param rbBgDrawableId 按钮背景，应为selector，分为state_checked="true"和state_checked="false"
     */
    public void setRbBgDrawableId(int rbBgDrawableId) {
        this.mRbBgDrawableId = rbBgDrawableId;

        initAllChildView();
    }

    /**
     * 设置页码输入界面状态
     *
     * @param showView 显示页码输入界面
     * @param gravity  不显示页码输入界面
     */
    public void setShowPageInputView(boolean showView, int gravity) {
        mShowJumpView = showView;
        mJumpViewGravity = gravity;

        initAllView();
    }

    /**
     * 是否显示页码输入界面
     *
     * @return true：显示；false：不显示
     */
    public boolean isShowPageInputView() {
        return mShowJumpView;
    }

    /**
     * 执行页码变化
     *
     * @param pageNumber 页码
     * @return true：执行了页码变化；false：未执行页码变化
     */
    private boolean disposePageChange(int pageNumber) {
        if (pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageNumber > mMaxPage) {
            pageNumber = mMaxPage;
        }
        if (mCurrPage == pageNumber) {
            return false;
        }
        mCurrPage = pageNumber;

        refreshPageNumRbText();

        refreshHomeTailViewVisibility();

        refreshJumpEtText();

        if (mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageChange(mCurrPage);
        }

        return true;
    }

    private final OnClickListener mOnClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            Object tag = v.getTag(KEY_PNV_BUTTON_TAG);
            if (!(tag instanceof Integer)) {
                return;
            }
            int tagInt = (int) tag;
            switch (tagInt) {
                case TYPE_BUTTON_LASTPAGE:
                    // 上一页
                    disposePageChange(mCurrPage - 1);
                    break;
                case TYPE_BUTTON_NEXTPAGE:
                    // 下一页
                    disposePageChange(mCurrPage + 1);
                    break;
                case TYPE_BUTTON_HOMEPAGE:
                    // 首页
                    disposePageChange(1);
                    break;
                case TYPE_BUTTON_TAILPAGE:
                    // 尾页
                    disposePageChange(mMaxPage);
                    break;
                case TYPE_BUTTON_JUMP:
                    // 跳转
                    String pageStr = mEtJump.getText().toString();
                    if (!TextUtils.isEmpty(pageStr)) {
                        int page = Integer.parseInt(pageStr);
                        if (!disposePageChange(Math.max(1, Math.min(mMaxPage, page)))) {
                            refreshJumpEtText();
                        }
                    } else {
                        refreshJumpEtText();
                    }
                    break;
                default:
                    // 数字页码
                    disposePageChange(tagInt);
                    break;
            }
        }
    };

    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
        this.mOnPageChangeListener = onPageChangeListener;

        if (mOnPageChangeListener != null) {
            mOnPageChangeListener.onPageChange(mCurrPage);
        }
    }

    public interface OnPageChangeListener {
        void onPageChange(int page);
    }
}
